(*******************************************************************
This file was generated automatically by the Mathematica front end.
It contains Initialization cells from a Notebook file, which
typically will have the same name as this file except ending in
".nb" instead of ".m".

This file is intended to be loaded into the Mathematica kernel using
the package loading commands Get or Needs.  Doing so is equivalent
to using the Evaluate Initialization Cells menu command in the front
end.

DO NOT EDIT THIS FILE.  This entire file is regenerated
automatically each time the parent Notebook file is saved in the
Mathematica front end.  Any changes you make to this file will be
overwritten.
***********************************************************************)

(* :Title: Surface Graphics *)

(* :Author: Roman E. Maeder, extended by Greg Humphreys *)

(* :Summary:
  A data type for surfaces in 3D, including normal vectors.
*)

(* :Context: MathProg`SurfaceGraphics3D` *)

(* :Package Version: 2.1 *)

(* :Copyright: Copyright 1994, Roman E. Maeder.

   Permission is granted to use and distribute this file for any purpose
   except for inclusion in commercial software or program collections.
   This copyright notice must remain intact.
*)

(* :History:
   Version 2.1 for PBRT, May 2005
   Version 2.0 for The Mathematica Programmer, Vol. 2, August 1995.
   Version 1.0 for the Mathematica Journal, June 1994.
*)

(* :Keywords: 
  surfaces, graphics, parametric plots
*)

(* :Source: 
    Maeder, Roman E. 1994. Ray Tracing and Graphics Extensions.
        The Mathematica Journal, 4(3).
*)

(* :Warning:
   Redefines the function ParametricPlot3D and Plot3D. 
*)

(* :Mathematica Version: 3.0 *)

(* :Discussion: 
   may optionally be used together with the package Graphics`ParametricPlot3D'.
   The main use of the new graphics data type is for external renderers
   that benefit from normal vectors to produce smooth surfaces.
*)

BeginPackage["PBRT`SurfaceGraphics3D`"]

SurfaceGraphics3D::usage="SurfaceGraphics3D[vertices, (normals,) {opts...}]
    represents a surface with given vertices and normals."
PlotScale::usage = 
  "Option to control the scaling of Plot3D output."

Begin["`Private`"]

Needs["Utilities`FilterOptions`"]

protected=Unprotect[SurfaceGraphics3D,ParametricPlot3D,Plot3D]

(*overload ParametricPlot3D[] to produce SurfaceGraphics3D*)

ParametricPlot3D[f_,{u_,u0_,u1_},{v_,v0_,v1_},opts___]:=
  Module[{plotpoints,ndu,ndv},
    plotpoints=PlotPoints/.{opts}/.Options[ParametricPlot3D];
    If[Head[plotpoints]=!=List,plotpoints={plotpoints,plotpoints}];
    plotpoints=plotpoints/.Automatic\[Rule]25;
    ndu=(u1-u0)/(plotpoints[[1]]-1);
    ndv=(v1-v0)/(plotpoints[[2]]-1);
    MakeSurface3D[f,{u,u0,u1,ndu},{v,v0,v1,ndv},opts]]

(*overload Plot3D[] to produce SurfaceGraphics3D*)

Plot3D[f_,{u_,u0_,u1_},{v_,v0_,v1_},opts___]:=
  Module[{plotpoints,ndu,ndv,plotscale},
    plotpoints=PlotPoints/.{opts}/.Options[Plot3D];
    Print[{opts}];
    plotscale = 
      PlotScale /. {opts} /. Options[Plot3D]  /. {PlotScale\[Rule]3.5};
    If[Head[plotpoints]=!=List,plotpoints={plotpoints,plotpoints}];
    plotpoints=plotpoints/.Automatic\[Rule]25;
    ndu=(u1-u0)/(plotpoints[[1]]-1);
    ndv=(v1-v0)/(plotpoints[[2]]-1);
    MakePlot3D[plotscale * f,{u,u0,u1,ndu},{v,v0,v1,ndv}, opts]]

(*compute normals*)

MakeSurface3D[f:{_,_,_},ur:{u_,_,_,_},vr:{v_,_,_,_},opts___]:=
  Module[{n,coords,surf,normals}, 
    n=Cross[D[f,v],D[f,u]];(*normal vectors*)coords=
      Table[N[{f,unit[n]}],ur,vr];
    {surf,normals}=Transpose[coords,{3,2,1}];
    If[And@@NumberQ/@Flatten[normals],
      SurfaceGraphics3D[surf,normals,{opts}],(*else:couldn't compute normals*)
        SurfaceGraphics3D[surf,{opts}]]]

(* version for non-parametric functions *) 
MakePlot3D[f_,ur:{u_,_,_,_},vr:{v_,_,_,_},opts___]:=
  Module[{n,coords,surf,normals},
    n={D[f,u],D[f,v],-1};(*normal vectors*)coords=
      Table[N[{{u,v, f},unit[n]}],ur,vr];
    {surf,normals}=Transpose[coords,{3,2,1}];
    If[And@@NumberQ/@Flatten[normals],
      SurfaceGraphics3D[surf,normals,{opts}],(*else:couldn't compute normals*)
        SurfaceGraphics3D[surf,{opts}]]]

unit[v_]:=v/Sqrt[Plus@@(v^2)]

(*strange functions.Do not attempt to produce normals*)

MakeSurface3D[f_,ur:{u_,_,_,_},vr:{v_,_,_,_},opts___]:=
  SurfaceGraphics3D[Table[N[f],ur,vr],{opts}]

(*convert to Graphics3D*)

makeMesh[vl_List]:=
  Module[{l=Drop[#,-1]&/@vl,l1=Drop[#,1]&/@vl,mesh},
    mesh={Drop[l,-1],Drop[l1,-1],Drop[l1,1],Drop[l,1]};
    Transpose[Flatten[#,1]&/@mesh]]

SurfaceGraphics3D/:
  Graphics3D[SurfaceGraphics3D[vl_List,normals_:{},{opts___}]]:=
  Graphics3D[Polygon/@makeMesh[vl],{FilterOptions[Graphics3D,opts]}]

SurfaceGraphics3D/:Show[s_SurfaceGraphics3D,opts___]:=
  Show[Graphics3D[s],opts]

SurfaceGraphics3D/:Display[file_,s_SurfaceGraphics3D,args___]:=
  Display[file,Graphics3D[s],args]

Format[_SurfaceGraphics3D]="-SurfaceGraphics3D-"

Protect[Evaluate[protected]]

End[]

EndPackage[]